const strDiscode = require('./strDiscode.js');
const utilsConfig = require('./utilsConfig.js');

let myNodeIndex = 0; // 节点数，也作为节点标识符

/**
 * 转换器
 * @param {string} html 要转换的html字符串
 */
const htmlParser = (html = '<div style="color: red;">文本不能为空</div>', {
  startTag = () => '',
  endTag = () => '',
  textTag = () => ''
} = {}) => {
  html = strDiscode(html);
  html = html.replace(/<mpchecktext([^\/]+)\/mpchecktext>/g, '');
  let isTextNode = true, // 是否是文本节点
    stack = [], // 节点栈
    last = html; // 异常标志
  stack.last = () => stack[stack.length - 1];

  /**
   * 开始标签转化函数
   * @param {string} tag 匹配全文
   * @param {string} tagName 当前匹配的标签名
   * @param {string} rest 当前匹配的标签属性
   * @param {string} unary 是否是一元标签
   */
  const parseStartTag = (tag, tagName, rest, unary) => {
    tagName = tagName.toLowerCase();

    if (utilsConfig.blockEleMap.has(tagName)) {
      while (stack.last() && utilsConfig.inlineEleMap.has(stack.last())) {
        parseEndTag('', stack.last());
      }
    }

    if (utilsConfig.closeSelfEleMap.has(stack.last()) && stack.last().tagName === tagName) {
      parseEndTag('', stack.last());
    }

    unary = utilsConfig.emptyEleMap.has(tagName) || !!unary;
    let curIndex = null;
    if (!unary) { stack.push({ tagName, id: myNodeIndex++ }); } // 非一元元素入栈
    else curIndex = myNodeIndex++;

    startTag({ tagName, rest, unary, stack, curIndex });
  }

  /**
   * 转换结束标签
   */
  const parseEndTag = (tag, tagName) => {
    let pos = 0;
    if (tagName) {
      for (pos = stack.length - 1; pos >= 0; pos--) {
        if (stack[pos].tagName === tagName) break;
      }
    }
    if (pos >= 0) {
      for (let i = stack.length - 1; i >= pos; i--) {
        endTag({ tagName: stack[i].tagName, stack });
      }
      stack.length = pos; // 移除末尾
    }
  }

  while (html) {
    isTextNode = true;

    // 结束标签
    if (html.indexOf('</') === 0) {
      let match = html.match(utilsConfig.endTagReg);

      if (match) {
        html = html.substring(match[0].length);
        isTextNode = false;
        match[0].replace(utilsConfig.endTagReg, parseEndTag);
      }
    }
    // 开始标签
    else if (html.indexOf('<') === 0) {
      let match = html.match(utilsConfig.startTagReg);
      
      if (match) {
        html = html.substring(match[0].length);
        isTextNode = false;
        match[0].replace(utilsConfig.startTagReg, parseStartTag);
      }
    }
    // 文本标签
    if (isTextNode) {
      let index = html.indexOf('<');
      let text = index < 0 ? html : html.substring(0, index);
      html = index < 0 ? '' : html.substring(index);
      textTag(text, stack);
    }

    if (html == last) throw new Error(`转换异常 ${html}`);
    last = html;
  }

  parseEndTag();

}

module.exports = htmlParser;